/**
 * ...
 * >author		João Vítor de Souza
 */

package com.cupcakeengine.display 
{
	import com.cupcakeengine.CKEngine;
	import com.cupcakeengine.core.IDestroyable;
	import com.cupcakeengine.ui.MouseManager;
	import flash.display.Stage;
	import flash.display.LoaderInfo;
	import flash.events.MouseEvent;
	import flash.geom.Transform;
	import flash.geom.Vector3D;
	import flash.display.Shader;
	import flash.accessibility.AccessibilityProperties;
	import flash.geom.Rectangle;	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.EventDispatcher;
	import flash.geom.Point;

	public class GameObject extends EventDispatcher implements IDisplayable, IDestroyable
	{
		// ___________________________________________________________________ CONSTANTS	
		
		// ___________________________________________________________________ CLASS PROPERTIES
		
		private var _buttonMode						: Boolean;
		private var _alpha							: Number;
		private var _scale							: Point;
		private var _x								: Number;
		private var _y								: Number;		
		private var _scaleX							: Number;
		private var _scaleY							: Number;
		private var _rotation						: Number;
		private var _parent							: GameObject;
		private var _vObject						: Vector.<GameObject>;
		
		// ___________________________________________________________________ INSTANCE PROPERTIES
		
		private var _display						: DisplayObject;
		private var _bitmapObject					: BitmapObject;
		private var _animation						: Animation;
		
		// ___________________________________________________________________ GETTERS AND SETTERS
		
		public function get display():DisplayObject { return _display; }
		
		public function get x():Number { return _x; }		
		
		public function set x(value:Number):void 
		{		
			_x = value;
			
			var px:int = _parent == null ? 0 : _parent.x;
			
			_bitmapObject.point.x = px + _x; 		
			
			var len:int = _vObject.length;
			var object:GameObject;
			for (var i:int = 0; i < len; i++) {
				object = _vObject[i];				
				object.x = object.x;
			}	
		}
		
		public function get y():Number { return _y; }
		
		public function set y(value:Number):void 
		{ 
			_y = value;
			
			var py:int = _parent == null ? 0 : _parent.y;
			
			_bitmapObject.point.y = py + _y; 			
			
			var len:int = _vObject.length;
			var object:GameObject;
			for (var i:int = 0; i < len; i++) {
				object = _vObject[i];
				object.y = object.y;
			}
		}
		
		public function get width():Number { return _bitmapObject.rectangle.width; }
		
		public function get height():Number { return _bitmapObject.rectangle.height; }
		
		public function get buttonMode():Boolean { return _buttonMode; }
		
		public function set buttonMode(value:Boolean):void 
		{
			_buttonMode = value;
			
			if (_buttonMode) {
				MouseManager.getInstance().addButtonMode(this);
			} else {
				MouseManager.getInstance().removeButtonMode(this);
			}
		}
		
		public function get alpha():Number { return _alpha; }
		
		public function set alpha(value:Number):void
		{
			_alpha = value;			
			
			_bitmapObject.setAlpha(_alpha);
			
			var len:int = _vObject.length;
			for (var i:int = 0; i < len; i++) {
				_vObject[i].alpha = _alpha;
			}
		}
		
		public function get scaleX():Number { return _scaleX; }
		
		public function set scaleX(value:Number):void 
		{
			if (value == _scaleX) return;			
			
			_bitmapObject.setScale(-1, _scaleY);
			
			_scaleX = value;
		}
		
		public function get scaleY():Number { return _scaleY; }
		
		public function set scaleY(value:Number):void 
		{			
			if (value == _scaleY) return;
			
			_bitmapObject.setScale(_scaleX, 1 + (value - _scaleY));			
			
			_scaleY = value;
		}
		
		public function get rotation():Number { return _rotation; }
		
		public function set rotation(value:Number):void 
		{		
			_bitmapObject.setRotation(value - _rotation);			
			
			_rotation = value;
		}
		
		public function get scale():Point { return _scale; }
		
		public function set scale(value:Point):void 
		{
			_scale = value;
		}
		
		public function get numObjects():int { return _vObject.length; }
		
		public function get parent():GameObject { return _parent; }		
		
		public function get animation():Animation { return _animation; }
		
		// ___________________________________________________________________ CONSTRUCTOR	
		
		public function GameObject (bitmapObject:BitmapObject)
		{
			_bitmapObject = bitmapObject;			
			
			_buttonMode = false;
			_alpha = 1;
			_x = 0;
			_y = 0;
			_scaleX = 1;
			_scaleY = 1;
			_scale = new Point(_scaleX, _scaleY);
			_rotation = 0;
			_vObject = new Vector.<GameObject>;			
			
			if(_bitmapObject.dBitmapData != null)			
			_animation = new Animation(_bitmapObject);
		}	
		
		// ___________________________________________________________________ PUBLIC METHODS
		
		/* INTERFACE com.cupcakeengine.display.IDisplayable */
		
		public function show(parent:GameObject = null):void 
		{
			if (_bitmapObject == null) return;
			_parent = parent;			
			if (_parent != null) {
				_parent.addChild(this);			
				this.alpha = _parent.alpha;
			}
			CKEngine.addToRenderer(_bitmapObject);
			
			if(_animation != null)
			CKEngine.addUpdate(_animation);
		}
		
		public function hide():void 
		{
			if(_animation != null)
			CKEngine.removeUpdate(_animation);
			
			if (_bitmapObject == null) return;
			CKEngine.removeFromRenderer(_bitmapObject);
		}
		
		/* INTERFACE com.cupcakeengine.core.IDestroyable */
		
		public function destroy():void 
		{
			hide();
			
			_parent = null;
			_vObject = null;
			
			if (_animation != null) _animation.destroy();
			_animation = null;
			
			_bitmapObject.destroy();
			_bitmapObject = null;
		}
		
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void 
		{
			//super.addEventListener(type, listener, useCapture, priority, useWeakReference);
			
			MouseManager.getInstance().addMouseEvent(this, type, listener);
		}
		
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void 
		{
			//super.removeEventListener(type, listener, useCapture);
			
			MouseManager.getInstance().removeMouseEvent(this, type);
		}
		
		public function hitTestObject(object:GameObject):Boolean
		{
			var x:Number = object.x;
			var y:Number = object.y;
			var width:Number = object.width;
			var height:Number = object.height;
			
			if (this.x < x + width && this.x + this.width > x) {
				if (this.y < y + height && this.y + this.height > y)
				return true;
			}
			
			return false;
		}
		
		public function setIndex(first:Boolean = true):void
		{			
			CKEngine.renderer.setIndex(_bitmapObject, first ? CKEngine.numObjects - 1 : 0);
		}
		
		public function addMouseEventListener(type:String, listener:Function):void
		{
			MouseManager.getInstance().addMouseEvent(this, type, listener);
		}
		
		public function removeMouseEventListener(type:String):void
		{
			MouseManager.getInstance().removeMouseEvent(this, type);
		}
		
		/*// flash.display.DisplayObject
		
		public function get visible():Boolean
		{
			return _display.visible;
		}
		
		public function get rotation():Number
		{
			return _display.rotation;
		}
		
		public function localToGlobal(point:Point):Point
		{
			return _display.localToGlobal(point);
		}
		
		public function get name():String
		{
			return _display.name;
		}
		
		public function set width(value:Number):void
		{
			_display.width = value;
		}
		
		public function globalToLocal(point:Point):Point
		{
			return _display.globalToLocal(point);
		}
		
		public function get blendMode():String
		{
			return _display.blendMode;
		}
		
		public function get scale9Grid():Rectangle
		{
			return _display.scale9Grid;
		}
		
		public function set name(value:String):void
		{
			_display.name = value;
		}
		
		public function get rotationX():Number
		{
			return _display.rotationX;
		}
		
		public function get rotationY():Number
		{
			return _display.rotationY;
		}
		
		public function set scaleX(value:Number):void
		{
			_display.scaleX = value;
		}
		
		public function set scaleY(value:Number):void
		{
			_display.scaleY = value;
		}
		
		public function set scaleZ(value:Number):void
		{
			_display.scaleZ = value;
		}
		
		public function get accessibilityProperties():AccessibilityProperties
		{
			return _display.accessibilityProperties;
		}
		
		public function set scrollRect(value:Rectangle):void
		{
			_display.scrollRect = value;
		}
		
		public function get rotationZ():Number
		{
			return _display.rotationZ;
		}
		
		public function get height():Number
		{
			return _display.height;
		}
		
		public function set blendMode(value:String):void
		{
			_display.blendMode = value;
		}
		
		public function set scale9Grid(innerRectangle:Rectangle):void
		{
			_display.scale9Grid = innerRectangle;
		}
		
		public function getBounds(targetCoordinateSpace:DisplayObject):Rectangle
		{
			return _display.getBounds(targetCoordinateSpace);
		}
		
		public function set blendShader(value:Shader):void
		{
			_display.blendShader = value;
		}
		
		public function get opaqueBackground():Object
		{
			return _display.opaqueBackground;
		}
		
		public function get parent():DisplayObjectContainer
		{
			return _display.parent;
		}
		
		public function get cacheAsBitmap():Boolean
		{
			
		}
		
		public function set rotationX(value:Number):void
		{
			
		}
		
		public function set rotationY(value:Number):void
		{
			
		}
		
		public function set rotationZ(value:Number):void
		{
			
		}
		
		public function local3DToGlobal(point3d:Vector3D):Point
		{
			
		}
		
		public function set alpha(value:Number):void
		{
			
		}
		
		public function globalToLocal3D(point:Point):Vector3D
		{
			
		}
		
		public function set accessibilityProperties(value:AccessibilityProperties):void
		{
			
		}
		
		public function get width():Number
		{
			
		}
		
		public function hitTestPoint(x:Number, y:Number, shapeFlag:Boolean = false):Boolean
		{
			
		}
		
		public function set cacheAsBitmap(value:Boolean):void
		{
			
		}
		
		public function get scaleX():Number
		{
			
		}
		
		public function get scaleY():Number
		{
			
		}
		
		public function get scaleZ():Number
		{
			
		}
		
		public function get scrollRect():Rectangle
		{
			
		}
		
		public function get mouseX():Number
		{
			
		}
		
		public function get mouseY():Number
		{
			
		}
		
		public function set height(value:Number):void
		{
			
		}
		
		public function set mask(value:DisplayObject):void
		{
			
		}
		
		public function getRect(targetCoordinateSpace:DisplayObject):Rectangle
		{
			
		}
		
		public function get alpha():Number
		{
			
		}
		
		public function set transform(value:Transform):void
		{
			
		}
		
		public function get loaderInfo():LoaderInfo
		{
			
		}
		
		public function get root():DisplayObject
		{
			
		}
		
		public function set visible(value:Boolean):void
		{
			
		}
		
		public function set opaqueBackground(value:Object):void
		{
			
		}
		
		public function hitTestObject(obj:DisplayObject):Boolean
		{
			
		}
		
		public function get mask():DisplayObject
		{
			
		}
		
		public function set x(value:Number):void
		{
			
		}
		
		public function set y(value:Number):void
		{
			
		}
		
		public function get transform():Transform
		{
			
		}
		
		public function set z(value:Number):void
		{
			
		}
		
		public function set filters(value:Array):void
		{
			
		}
		
		public function get x():Number
		{
			
		}
		
		public function get y():Number
		{
			
		}
		
		public function get z():Number
		{
			
		}
		
		public function get filters():Array
		{
			
		}
		
		public function set rotation(value:Number):void
		{
			
		}
		
		public function get stage():Stage
		{
			
		}*/
		
		// ___________________________________________________________________ PRIVATE METHODS
		
		private function addChild(child:GameObject):void
		{
			_vObject.push(child);			
		}
		
		// ___________________________________________________________________ EVENTS
	}
}

 